home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / audio / glib.3 < prev   
Text File  |  1989-03-16  |  54KB  |  2,400 lines

  1. Path: xanth!ames!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i073:  glib - generic librarian/editor for synths, Part03/03
  5. Message-ID: <12289@swan.ulowell.edu>
  6. Date: 16 Mar 89 16:55:44 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2389
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: mab@druwy.att.com (Alan Bland)
  12. Posting-number: Volume 89, Issue 73
  13. Archive-name: audio/glib.3
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    glib.c
  23. #    yama_com.c
  24. # This archive created: Thu Mar 16 11:45:30 1989
  25. cat << \SHAR_EOF > glib.c
  26. /*
  27.  * GLIB - a Generic LIBrarian and editor for synths
  28.  */
  29.  
  30. #include "glib.h"
  31. #include <ctype.h>
  32.  
  33. char *Reason = "";
  34.  
  35. int Currrow = 0;    /* at top of screen, for messages */
  36. int Libbank = 0;    /* from 0 to LIBBANKS-1, is the current library bank*/
  37. int Nsynths = 0;
  38.  
  39. char *Currdata;
  40. char *Yankdata;        /* current 'yank' buffer (middle of screen) */
  41.  
  42. struct peredinfo *PE;    /* array of per-editor miscellany */
  43.  
  44. char Buff[BUFSIZ];
  45. int Redraw = 0;        /* if non-0, edit screen is completely redrawn. */
  46.             /* parameter functions can make use of this. */
  47. int Changed = 0;
  48.  
  49. /* All the global values below are set as appropriate for the */
  50. /* synthesizer currently being dealt with. */
  51.  
  52. int Nvoices = 0;
  53. int Voicesize =0;
  54. int Namesize = 0;
  55. int Libindex;        /* from 0 to Nvoices-1 */
  56. int Synindex;        /* from 0 to Nvoices-1 */
  57. int Channel;
  58. int Editrow;        /* from 0 to NUMONSCREEN-1 */
  59. int Editcol;        /* 0==synth, 1==library */
  60. char *Libdata;        /* current library data (includes all LIBBANKS) */
  61.             /* ie. the stuff on the right side of the screen */
  62. char *Syndata;        /* current synth data (1 bank), ie. the left side */
  63. struct paraminfo *P;    /* list of parameter info */
  64. struct labelinfo *L;    /* arbitrary screen labels for edit screen */
  65. char *Synthname;
  66.  
  67. int (*Sendedit)();    /* function to send parameters to synth's edit buffer*/
  68. int (*Datain)();    /* convert data from file-storage format to the */
  69.             /* format stored in the P[] parameter array (p_val) */
  70. int (*Dataout)();    /* reverse of Datain */
  71. int (*Sendone)();    /* function to send one (permanent) voice to synth */
  72. int (*Sendbulk)();    /* function to send bulk dump to synth */
  73. int (*Getbulk)();    /* reverse of Sendbulk */
  74. char *(*Nameof)();    /* pulls voice name out of file-storage data */
  75. int (*Setnameof)();    /* reverse of Nameof */
  76. char *(*Numof)();    /* convert voice number to on-screen text */
  77. int (*Cvtnum)();    /* convert visible voice number to std. format */
  78. int (*Cvtanum)();    /* convert alphanumeric voice number to std. format */
  79.             /* should never define both Cvtnum and Cvtanum */
  80. main()
  81. {
  82.     int n;
  83.  
  84.     hello();
  85.     windinit();
  86.     initstuff();
  87.  
  88.     if ( Nsynths == 0 )
  89.         windstr("Hey, the E array is empty?");
  90.     else if ( Nsynths == 1 ) {
  91.         /* If there's only 1 synth, don't bother asking */
  92.         setedit(0);
  93.         libinteract();
  94.     }
  95.     else {
  96.         while ( (n=choosesynth()) >= 0 ) {
  97.             setedit(n);
  98.             libinteract();
  99.             unsetedit(n);
  100.         }
  101.     }
  102.     bye();
  103. }
  104.  
  105. /* choose a synth, returning its position in the E array */
  106. choosesynth()
  107. {
  108.     int n, pick;
  109.  
  110.     retry:
  111.     flushconsole();
  112.     windclear();
  113.     windgoto(2,18);
  114.     windstr("GLIB - A Generic Librarian/Editor");
  115.  
  116.     for ( n=1; n<=Nsynths; n++ )
  117.         libchoice(n);
  118.  
  119.     windgoto(10+n,16);
  120.     windstr("Choose your synth (or 'q' to quit) --> ");
  121.     windrefresh();
  122.     pick = mouseorkey();
  123.     if ( pick == 'q' || pick == EOF )
  124.         return(-1);
  125.     if ( pick != MOUSE )
  126.         pick = pick - '0';
  127.     else {
  128.         int row, col;
  129.         getmouse(&row,&col);
  130.         /* wait until mouse goes down */
  131.         while ( statmouse() > 0 )
  132.             ;
  133.         pick = row - 6; 
  134.     }
  135.     if ( pick < 1 || pick > Nsynths )
  136.         goto retry;
  137.     return(pick-1);
  138. }
  139.  
  140. libchoice(n)
  141. {
  142.     windgoto(6+n,27);
  143.     sprintf(Buff,"%d  -  %s",n,E[n-1].ed_name);
  144.     windstr(Buff);
  145. }
  146.  
  147. initstuff()
  148. {
  149.     int n, banksize, maxvsize = 0;
  150.     char *p;
  151.     
  152.     for ( n=0; E[n].ed_name != NULL; n++ ) {
  153.         if ( maxvsize < E[n].ed_vsize )
  154.             maxvsize = E[n].ed_vsize;
  155.     }
  156.     Nsynths = n;
  157.     Currdata = alloc( maxvsize );
  158.  
  159.     /* allocate an array of peredinfo structs */
  160.     PE =(struct peredinfo *)alloc((int)(Nsynths*sizeof(struct peredinfo)));
  161.     for ( n=0; n<Nsynths; n++ ) {
  162.         banksize =  E[n].ed_nvoices * E[n].ed_vsize;
  163.         p = PE[n].ed_libdata = alloc( LIBBANKS * banksize );
  164.         clrdata(p,LIBBANKS*banksize);
  165.         p = PE[n].ed_syndata = alloc( banksize );
  166.         clrdata(p,banksize);
  167.         p = PE[n].ed_yankdata = alloc( E[n].ed_vsize );
  168.         clrdata(p,E[n].ed_vsize);
  169.         PE[n].ed_libindex = 0;
  170.         PE[n].ed_synindex = 0;
  171.         PE[n].ed_channel = 1;
  172.         PE[n].ed_erow = 0;
  173.         PE[n].ed_ecol = 0;
  174.     }
  175. }
  176.  
  177. clrdata(data,size)
  178. char *data;
  179. {
  180.     register char *p = data, *endp = data+size;
  181.  
  182.     while ( p<endp )
  183.         *p++ = 0;
  184. }
  185.  
  186. setedit(n)
  187. {
  188.     Synthname = E[n].ed_name;
  189.     Datain = E[n].ed_din;
  190.     Dataout = E[n].ed_dout;
  191.     Nvoices = E[n].ed_nvoices;
  192.     Sendedit = E[n].ed_sedit;
  193.     Sendone = E[n].ed_sone;
  194.     Sendbulk = E[n].ed_sbulk;
  195.     Getbulk = E[n].ed_gbulk;
  196.     Nameof = E[n].ed_nof;
  197.     Numof = E[n].ed_numof;
  198.     Cvtnum = E[n].ed_cvtnum;
  199.     Cvtanum = E[n].ed_cvtanum;
  200.     Setnameof = E[n].ed_snof;
  201.     Voicesize = E[n].ed_vsize;
  202.     Namesize = E[n].ed_nsize;
  203.     Libdata = PE[n].ed_libdata;
  204.     Syndata = PE[n].ed_syndata;
  205.     Yankdata = PE[n].ed_yankdata;
  206.     Libindex = PE[n].ed_libindex;
  207.     Synindex = PE[n].ed_synindex;
  208.     Channel = PE[n].ed_channel;
  209.     Editrow = PE[n].ed_erow;
  210.     Editcol = PE[n].ed_ecol;
  211.     clrdata(Currdata,Voicesize);
  212.     P = E[n].ed_params;
  213.     L = E[n].ed_labels;
  214. }
  215.  
  216. unsetedit(n)
  217. {
  218.     int k;
  219.  
  220.     PE[n].ed_libindex = Libindex;
  221.     PE[n].ed_synindex = Synindex;
  222.     PE[n].ed_channel = Channel;
  223.     PE[n].ed_erow = Editrow;
  224.     PE[n].ed_ecol = Editcol;
  225.     for ( k=0; k<Voicesize; k++ )
  226.         PE[n].ed_yankdata[k] = Yankdata[k];
  227. }
  228.  
  229. /* template - show the boxes and such on the main library screen */
  230. template()
  231. {
  232.     int n, k, r;
  233.  
  234.     r = FIRSTROW-1;
  235.     sprintf(Buff,"%s Voices",Synthname);
  236.     n = 13 - strlen(Buff)/2;    /* center it */
  237.     windgoto(r,n<0?0:n);
  238.     windstr(Buff);
  239.     r++;
  240.     windgoto(r,0);
  241.     for ( n=0; n<26; n++ )
  242.         windputc('=');
  243.     windgoto(r,52);
  244.     for ( n=0; n<26; n++ )
  245.         windputc('=');
  246.     for ( n=r+1; n<(r+13); n++ ) {
  247.         windgoto(n,0);
  248.         windputc('|');
  249.         windgoto(n,6);
  250.         windputc('|');
  251.         windgoto(n,25);
  252.         windputc('|');
  253.  
  254.         k=52;
  255.         windgoto(n,k);
  256.         windputc('|');
  257.         windgoto(n,k+6);
  258.         windputc('|');
  259.         windgoto(n,k+25);
  260.         windputc('|');
  261.     }
  262.     windgoto(r+13,0);
  263.     for ( n=0; n<26; n++ )
  264.         windputc('=');
  265.     windgoto(r+13,52);
  266.     for ( n=0; n<26; n++ )
  267.         windputc('=');
  268.  
  269.     windgoto(YANKROW-2,YANKCOL);
  270.     windstr("  Yank Buffer");
  271.     windgoto(YANKROW-1,YANKCOL);
  272.     windstr(" ------------- ");
  273.     windgoto(YANKROW,YANKCOL);
  274.     windstr("               ");
  275.     windgoto(YANKROW+1,YANKCOL);
  276.     windstr(" ------------- ");
  277.     windrefresh();
  278. }
  279.  
  280. /* clear the message area */
  281. clearmess()
  282. {
  283.     int n;
  284.     for(n=1;n<(FIRSTROW-1);n++)
  285.         winderaserow(n);
  286.     Currrow = 0;
  287. }
  288.  
  289. /* set the current voice (ie. the synth's edit buffer) to the indicated */
  290. /* voice.  c==0 is the synth (left) side, c==1 is the library (right) side. */
  291. editto(r,c)
  292. {
  293.     int voicenum;
  294.  
  295.     /* Clear the existing '*' */
  296.     editchar(' ',Editrow,Editcol);
  297.     editchar('*',Editrow=r,Editcol=c);
  298.     if ( Editcol==0 ) {
  299.         /* we're on the synth side */
  300.         voicenum = Editrow+Synindex;
  301.         tocurrent(Syndata,voicenum);
  302.     }
  303.     else {
  304.         /* we're on the lib side */
  305.         voicenum = Editrow+Libindex;
  306.         tocurrent(bankvoice(0),voicenum);
  307.     }
  308. }
  309.  
  310. editchar(ec,r,c)
  311. {
  312.     r = r + FIRSTROW + 1;
  313.     if ( c == 0 )
  314.         c = LEFTSIDE-1;
  315.     else
  316.         c = RIGHTSIDE-1;
  317.     windgoto(r,c);
  318.     windputc(ec);
  319.     windrefresh();
  320. }
  321.  
  322. /* control interaction on the main library bank screen */
  323. libinteract()
  324. {
  325.     int c, n, swap, voicenum, maxindex;
  326.     char *p, *data;
  327.  
  328.     flushmidi();
  329.     drawall();
  330.     for ( ;; ) {
  331.         Currrow = 0;
  332.         winderaserow(Currrow);
  333.         windgoto(Currrow,0);
  334.         windstr("Command --> ");
  335.         windrefresh();
  336.         
  337.         c = mouseorkey();
  338.         if ( c == MOUSE ) {
  339.             libmouse();
  340.             continue;
  341.         }
  342.  
  343.         if ( isprint(c) )
  344.             windputc(c);
  345.         clearmess();
  346.         switch ( c ) {
  347.         case ' ':
  348.             playnote(1);
  349.             break;
  350.         case '\n':
  351. #ifndef macintosh
  352.         case '\r':
  353. #endif
  354.             /* ignore */
  355.             break;
  356.         case EOF:
  357.         case 'q':
  358.             return;
  359.         case CH_REDRAW:
  360.             drawall();
  361.             break;
  362.         case 's':
  363.         case 'p':
  364.             swap = (c=='s')?1:0;
  365.             if ( Editcol==0 )
  366.                 tosyn(Synindex+Editrow,Yankdata,swap);
  367.             else
  368.                 tolib(Libindex+Editrow,Yankdata,swap);
  369.             updatedisplay();
  370.             pryankname();
  371.             break;
  372.         case 'y':
  373.             for(n=0;n<Voicesize;n++)
  374.                 Yankdata[n] = Currdata[n];
  375.             pryankname();
  376.             break;
  377.         case '?':
  378.             helpmessage();
  379.             break;
  380.         case SCR_DOWN:
  381.             maxindex = Nvoices - NUMONSCREEN;
  382.             if ( Editcol==0 ) {
  383.                 /* we're on the synth side */
  384.                 if ( (Synindex+=NUMONSCREEN/2) > maxindex )
  385.                     Synindex = maxindex;
  386.             }
  387.             else {
  388.                 /* we're on the lib side */
  389.                 if ( (Libindex+=NUMONSCREEN/2) > maxindex )
  390.                     Libindex = maxindex;
  391.             }
  392.             updatedisplay();
  393.             break;
  394.         case SCR_UP:
  395.             if ( Editcol==0 ) {
  396.                 /* we're on the synth side */
  397.                 if ( (Synindex-=NUMONSCREEN/2) < 0 )
  398.                     Synindex = 0;
  399.             }
  400.             else {
  401.                 /* we're on the lib side */
  402.                 if ( (Libindex-=NUMONSCREEN/2) < 0 )
  403.                     Libindex = 0;
  404.             }
  405.             updatedisplay();
  406.             break;
  407.         case '\033':
  408.         case '`':
  409.             allnotesoff();
  410.             break;
  411.         case 't':
  412.             transcmd();
  413.             break;
  414.         case 'd':    /* download from synth to display */
  415.             clrdata(Syndata,Nvoices*Voicesize);
  416.             if ( readsynth(Syndata) == 0 )
  417.                 syntodisplay(Synindex=0);
  418.             break;
  419.         case 'u':    /* upload TO synth */
  420.             if ( Editcol==0 ) {
  421.                 voicenum = Editrow+Synindex;
  422.                 data = &(VOICEBYTE(Syndata,voicenum,0));
  423.             }
  424.             else
  425.                 data = bankvoice(Editrow+Libindex);
  426.             upload(data);
  427.             break;
  428.         case 'r':
  429.             readall();
  430.             break;
  431.         case 'w':
  432.             writeall();
  433.             break;
  434.         case 'c':
  435.             setchan();
  436.             break;
  437.         case 'b':
  438.             /* cycle through banks, from 0 to LIBBANKS-1 */
  439.             if ( ++Libbank >= LIBBANKS )
  440.                 Libbank = 0;
  441.             libtodisplay(Libindex);
  442.             updatedisplay();
  443.             break;
  444.         case 'e':
  445.             p = (*Nameof)(Currdata);
  446.             if ( Editcol==0 ) {
  447.                 voicenum = Editrow+Synindex;
  448.                 data = &(VOICEBYTE(Syndata,voicenum,0));
  449.                 editdata(p,data);
  450.                 windclear();
  451.                 /* Update Currdata */
  452.                 for ( n=0; n<Voicesize; n++ )
  453.                     Currdata[n] = VOICEBYTE(Syndata,voicenum,n);
  454.             }
  455.             else {
  456.                 data = bankvoice(Editrow+Libindex);
  457.                 editdata(p,data);
  458.             }
  459.             drawall();
  460.             break;
  461.         case 'g': /* goto a specific voice */
  462.             do_goto();
  463.             break;
  464.         case CH_LEFT:
  465.             if ( Editcol==1 )
  466.                 editto(Editrow,0);
  467.             break;
  468.         case CH_DOWN:
  469.             if ( Editrow < (NUMONSCREEN-1) )
  470.                 editto(Editrow+1,Editcol);
  471.             else {
  472.                 /* we're at the bottom, so try to scroll */
  473.                 if ( Editcol==0 ) {
  474.                     /* we're on the synth side */
  475.                     if (Synindex<(Nvoices-NUMONSCREEN))
  476.                         Synindex++;
  477.                 }
  478.                 else {
  479.                     /* we're on the lib side */
  480.                     if (Libindex<(Nvoices-NUMONSCREEN))
  481.                         Libindex++;
  482.                 }
  483.                 updatedisplay();
  484.             }
  485.             break;
  486.         case CH_UP:
  487.             if ( Editrow>0 )
  488.                 editto(Editrow-1,Editcol);
  489.             else {
  490.                 /* we're at the top, so try to scroll */
  491.                 if ( Editcol==0 ) {
  492.                     /* we're on the synth side */
  493.                     if (Synindex>0)
  494.                         Synindex--;
  495.                 }
  496.                 else {
  497.                     /* we're on the lib side */
  498.                     if (Libindex>0)
  499.                         Libindex--;
  500.                 }
  501.                 updatedisplay();
  502.             }    
  503.             break;
  504.         case CH_RIGHT:
  505.             if ( Editcol==0 )
  506.                 editto(Editrow,1);
  507.             break;
  508.         case 'f':
  509.             filelist();
  510.             break;
  511.         default:
  512.             message("Unrecognized command!  Press '?' for help.");
  513.             break;
  514.         }
  515.     }
  516. }
  517.  
  518. filelist()
  519. {
  520.     char *p, *q, buff[BUFSIZ];
  521.     int n, ninline = 0, nprinted = 0;
  522.  
  523.     clearmess();
  524.     Currrow = -1;    /* To start message on top line */
  525.     openls();
  526.     message("Files in current directory:");
  527.     strcpy(buff,"  ");
  528.     while ( (p=nextls()) != NULL ) {
  529.         /* add the next file to the line being constructed */
  530.         q = &buff[strlen(buff)];
  531.         strcpy(q,p);
  532.         q += (n=strlen(p));
  533.         while ( n++ < 15 )
  534.             *q++ = ' ';
  535.         *q = '\0';
  536.         if ( ninline++ > 3 ) {
  537.             message(buff);
  538.             if ( nprinted++ > 4 ) {
  539.                 message("Press any key to continue ...");
  540.                 getconsole();
  541.                 clearmess();
  542.                 nprinted = 0;
  543.             }
  544.             strcpy(buff,"  ");
  545.             ninline = 0;
  546.         }
  547.     }
  548.     if ( ninline > 0 )
  549.         message(buff);
  550.     closels();
  551. }
  552.  
  553. libmouse()
  554. {
  555.     int row, col;
  556.  
  557.     getmouse(&row,&col);
  558.     if ( row <= FIRSTROW || row > FIRSTROW+NUMONSCREEN+1 )
  559.         goto getout;
  560.     if ( col < Cols/2 )
  561.         col = 0;
  562.     else
  563.         col = 1;
  564.     row = row - FIRSTROW - 1;
  565.     editto(row,col);
  566. getout:
  567.     /* wait until mouse button is released */
  568.     while ( statmouse() > 0 )
  569.         ;
  570. }
  571.  
  572. do_goto()
  573. {
  574.     int n, r, maxindex, new_ecol;
  575.     char sbuf[100], *sp;
  576.     
  577.     message("");
  578.     message("Where to? ");
  579.     windgets(sbuf);
  580.     
  581.     sp = sbuf;
  582.     switch(*sp++) {
  583.       case 's': /* synth side */
  584.         new_ecol = 0;
  585.         break;
  586.       case 'l': /* library side */
  587.         new_ecol = 1;
  588.         break;
  589.       default: /* no change in side */
  590.           new_ecol = Editcol;
  591.         sp--;    /* but don't trash the first character */
  592.         break;
  593.     }
  594.     
  595.     clearmess();
  596.     r = sscanf(sp, "%d", &n); /* this may fail - we handle it later */
  597.     if(Cvtnum != NULL) { /* convert to internal format if needed */
  598.         n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */
  599.     }
  600.     if (Cvtanum != NULL) { /* convert using alphanumeric voice number */
  601.         n = (*Cvtanum)(sp) + 1;
  602.     }
  603.     if(r != 1) {
  604.         message("type one of: sn, ln, or n");
  605.         message("  s = synth side (literal character 's')");
  606.         message("  l = library side (literal character 'l')");
  607.         message("  n = voice number to select (an integer)");
  608.         return;
  609.     }
  610.     if(n <= 0 || n > Nvoices) { /* 1-based */
  611.         message("Bad voice number!");
  612.         return;
  613.     }
  614.     
  615.     /* it can be done.  nuke the old '*' and change columes (if needed) */
  616.     editchar(' ', Editrow, Editcol);
  617.     Editcol = new_ecol;
  618.     
  619.     /* try to center it */
  620.     maxindex = Nvoices - NUMONSCREEN;
  621.     if(Editcol == 0) {
  622.         Synindex = (n - 1) - NUMONSCREEN/2; /* 0-based */
  623.         if(Synindex < 0) { /* impossible to center */
  624.             Synindex = 0; /* so do your best */
  625.         } else if(Synindex > maxindex) {
  626.             Synindex = maxindex;
  627.         }
  628.         Editrow = (n - 1) - Synindex; /* and put a '*' on it */
  629.     } else {
  630.         Libindex = (n - 1) - NUMONSCREEN/2; /* 0-based */
  631.         if(Libindex < 0) {
  632.             Libindex = 0;
  633.         } else if(Libindex > maxindex) {
  634.             Libindex = maxindex;
  635.         }
  636.         Editrow = (n - 1) - Libindex;
  637.     }
  638.     
  639.     updatedisplay(); /* do the real work */
  640.     return;
  641. }
  642.  
  643. upload(data)
  644. char *data;
  645. {
  646.     int c, n;
  647.     char num[16];
  648.  
  649.     message("");
  650.     message("Upload TO synth:");
  651.     message("                 c - current voice");
  652.     message("                 a - ALL voices");
  653.     message("Choose --> ");
  654.     c = getconsole();
  655.     if ( c == 'c' ) {
  656.         clearmess();
  657.         if ( Sendone == NULL ) {
  658.             message("Single voices can't be sent to that synth!");
  659.             return;
  660.         }
  661.         message("What voice number to you want to send it TO? --> ");
  662.         windgets(num);
  663.         clearmess();
  664.         n = atoi(num);
  665.         if(Cvtnum != NULL) { /* convert to internal format if needed */
  666.             n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */
  667.         }
  668.         if (Cvtanum != NULL) { /* howzabout alphanumeric format? */
  669.             n = (*Cvtanum)(num) + 1;
  670.         }
  671.         if ( n > 0 && n <= Nvoices ) {
  672.             if ( (*Sendone)(n-1,data) != 0 ) { /* 0-based on calls -SAF */
  673.                 message("Unable to write data to synth!");
  674.                 sprintf(Buff,"Reason: %s",Reason);
  675.                 message(Buff);
  676.             }
  677.         } else {
  678.             message("Bad voice number!");
  679.         }
  680.     }
  681.     else if ( c == 'a' ) {
  682.         clearmess();
  683.         if ( Sendbulk != NULL )
  684.             (*Sendbulk)(Syndata);
  685.         else {
  686.             for ( n=0; n<Nvoices; n++ ) {
  687.                 if ( (*Sendone)(n, &(VOICEBYTE(Syndata,n,0)) ) != 0 ) {
  688.                     message("Unable to write data to synth!");
  689.                     sprintf(Buff,"Reason: %s",Reason);
  690.                     message(Buff);
  691.                     break;
  692.                 }
  693.             }
  694.         }
  695.         /* clearmess(); */
  696.     }
  697.     else {
  698.         clearmess();
  699.         message("Bad choice!");
  700.     }
  701. }
  702.  
  703. helpmessage()
  704. {
  705. clearmess();
  706. sprintf(Buff,"%s,%s,%s,%s - move around              e - edit current voice",
  707.     STR_LEFT,STR_DOWN,STR_UP,STR_RIGHT);
  708. message(Buff);
  709. message("r - read voices from a file        y - yank into buffer");
  710. message("w - write voices to a file         p - put from buffer");
  711. message("b - cycle through library banks    s - swap current voice with yank buffer");
  712. message("t - transfer all voices            f - list files in current directory");
  713. message("d - download voices from synth     c - set MIDI channel");
  714. message("u - upload voices to synth         g - 'goto' form of moving around");
  715. message("q - quit                           <space> - play a note");
  716. }
  717.  
  718. updatedisplay()
  719. {
  720.     if ( Editcol==0 ) {
  721.         /* we're on the synth side */
  722.         syntodisplay(Synindex);
  723.         editto(Editrow,Editcol);
  724.     }
  725.     else {
  726.         /* we're on the lib side */
  727.         libtodisplay(Libindex);
  728.         editto(Editrow,Editcol);
  729.     }
  730. }
  731.  
  732. pryankname()
  733. {
  734.     char ybuff[33];
  735.     char *p;
  736.  
  737.     windgoto(YANKROW,YANKCOL-4);
  738.     windstr("                    ");
  739.     strcpy(ybuff,(*Nameof)(Yankdata));
  740.     /* take off trailing blanks */
  741.     p = ybuff + strlen(ybuff) - 1;
  742.     while ( p>ybuff && *p == ' ' )
  743.         *p-- = '\0';
  744.     windgoto(YANKROW,YANKCOL+7-strlen(ybuff)/2);
  745.     windstr(ybuff);
  746.     windrefresh();
  747. }
  748.  
  749. transcmd()
  750. {
  751.     int fromc;
  752.  
  753.     message("");
  754.     message("Transfer ALL voices:");
  755.     message("                       1:   <<-----   from library bank to synth bank");
  756.     message("                       2:   ----->>   from synth bank to library bank");
  757.     message("1 or 2 --> ");
  758.     fromc = getconsole();
  759.     windputc(fromc);
  760.     if ( fromc!='1' && fromc!='2' ) {
  761.         clearmess();
  762.         return;
  763.     }
  764.     switch ( fromc ) {
  765.     case '1':
  766.         copyall(bankvoice(0),Syndata);
  767.         syntodisplay(Synindex);
  768.         clearmess();
  769.         message("Use the 'u'pload command to actually send the synth bank voices to the synth.");
  770.         break;
  771.     case '2':
  772.         copyall(Syndata,bankvoice(0));
  773.         libtodisplay(Libindex);
  774.         clearmess();
  775.         break;
  776.     }
  777. }
  778.  
  779. copyall(fromdata,todata)
  780. char *fromdata;
  781. char *todata;
  782. {
  783.     int n, v;
  784.  
  785.     for ( v=0; v<Nvoices; v++ )
  786.         for ( n=0; n<Voicesize; n++ )
  787.             VOICEBYTE(todata,v,n) = VOICEBYTE(fromdata,v,n);
  788. }
  789.  
  790. message(s)
  791. char *s;
  792. {
  793.     windgoto(++Currrow,0);
  794.     windstr(s);
  795.     windrefresh();
  796. }
  797.  
  798. setchan()
  799. {
  800.     int c;
  801.  
  802.     message("New MIDI channel --> ");
  803.     windgets(Buff);
  804.     if ( (c=atoi(Buff)) <= 0 || c > 16 ) {
  805.         clearmess();
  806.         message("Invalid channel!");
  807.     }
  808.     else {
  809.         clearmess();
  810.         Channel = c;
  811.         showchan();
  812.     }
  813. }
  814.  
  815. showchan()
  816. {
  817.     windgoto(20,31);
  818.     windstr("MIDI Channel: ");
  819.     sprintf(Buff,"%d ",Channel);
  820.     windstr(Buff);
  821.     windrefresh();
  822. }
  823.  
  824. /* read data from a file, filling the current library bank. */
  825. readall()
  826. {
  827.     char fname[100];
  828.     FILE *f;
  829.     int v, n, r;
  830.  
  831.     message("File name --> ");
  832.     windgets(fname);
  833.     OPENBINFILE(f,fname,"r");
  834.     if (f == NULL ) {
  835.         sprintf(Buff,"Can't open '%s'!",fname);
  836.         message(Buff);
  837.         return;
  838.     }
  839.     /* Check the first byte.  If it's 0xdd, then the format is mine. */
  840.     /* If the first byte is 0-31, it's also mine. */
  841.     n = (getc(f) & 0xff);
  842.     if ( n == 0xdd || n<=31 ) {
  843.         if ( n <= 31 )
  844.             ungetc(n,f);
  845.         /* This is my format, just raw data. */
  846.         for ( v=0; v<Nvoices; v++ ) {
  847.             char *p = bankvoice(v);
  848.             for ( n=0; n<Voicesize; n++ )
  849.                 *p++ = getc(f);
  850.         }
  851.         r = 0;
  852.     }
  853.     /* code for other formats would go here */
  854.     else {
  855.         message("Unknown file format");
  856.         r = 1;
  857.     }
  858.     fclose(f);
  859.     if ( r==0 ) {
  860.         libtodisplay(Libindex=0);
  861.         clearmess();
  862.     }
  863. }
  864.  
  865. /* write current library bank to a file */
  866. writeall()
  867. {
  868.     char fname[100];
  869.     FILE *f;
  870.     int v, n;
  871.  
  872.     message("File name --> ");
  873.     windgets(fname);
  874.     OPENBINFILE(f,fname,"w");
  875.     if ( f == NULL ) {
  876.         sprintf(Buff,"Can't open '%s'!",fname);
  877.         message(Buff);
  878.         return;
  879.     }
  880.     putc(0xdd,f);    /* magic byte to identify my format */
  881.     for ( v=0; v<Nvoices; v++ ) {
  882.         char *p = bankvoice(v);
  883.         for ( n=0; n<Voicesize; n++ )
  884.             putc(*p++,f);
  885.     }
  886.     fclose(f);
  887.     clearmess();
  888. }
  889.  
  890. /* draw main library/synth voice bank screen */
  891. drawall()
  892. {
  893.     windclear();
  894.     template();
  895.     libtodisplay(Libindex);
  896.     syntodisplay(Synindex);
  897.     editto(Editrow,Editcol);
  898.     pryankname();
  899.     showchan();
  900. }
  901.  
  902. /*
  903.  * tosyn
  904.  *
  905.  * Store the given 'data' in in voice 'voicenum' (both in Syndata
  906.  * AND on the synth itself).  If swap is non-zero, the voice is swapped
  907.  * with the current voice in Syndata.
  908.  */
  909.  
  910. tosyn(voicenum,data,swap)
  911. char *data;
  912. {
  913.     int n, t;
  914.  
  915.     for ( n=0; n<Voicesize; n++ ) {
  916.         if ( swap ) {
  917.             t = VOICEBYTE(Syndata,voicenum,n);
  918.             VOICEBYTE(Syndata,voicenum,n) = data[n];
  919.             data[n] = t;
  920.         }
  921.         else
  922.             VOICEBYTE(Syndata,voicenum,n) = data[n];
  923.     }
  924. }
  925.  
  926. tolib(voicenum,data,swap)
  927. char *data;
  928. {
  929.     int n, t;
  930.     char *p = bankvoice(voicenum);
  931.  
  932.     for ( n=0; n<Voicesize; n++ ) {
  933.         if ( swap ) {
  934.             t = *p;
  935.             *p = data[n];
  936.             data[n] = t;
  937.         }
  938.         else
  939.             *p = data[n];
  940.         p++;
  941.     }
  942. }
  943.  
  944. tocurrent(data,voicenum)
  945. char *data;
  946. int voicenum;
  947. {
  948.     int n;
  949.  
  950.     for ( n=0; n<Voicesize; n++ )
  951.         Currdata[n] = VOICEBYTE(data,voicenum,n);
  952.     (*Sendedit)(Currdata);
  953. }
  954.  
  955. /*
  956.  * readsynth
  957.  *
  958.  * Read a bulk dump from the synth, with some tolerance for errors.
  959.  */
  960. readsynth(data)
  961. char *data;
  962. {
  963.     if ( Getbulk == NULL ) {
  964.         message("That synth is unable to dump anything!!");
  965.         return(1);
  966.     }
  967.     message("Trying to download data from synth...");
  968.     if ( (*Getbulk)(data) == 0 ) {
  969.         clearmess();
  970.         return(0);
  971.     }
  972.     message("Unable to read data from synth!");
  973.     sprintf(Buff,"Reason: %s",Reason);
  974.     message(Buff);
  975.     message("Perhaps connections are amiss?");
  976.     return(1);
  977. }
  978.  
  979. char *
  980. vnumtext(n)
  981. {
  982.     static char vnbuff[6];
  983.  
  984.     if ( Numof == NULL ) {
  985.         sprintf(vnbuff,"%2d",n);
  986.         return(vnbuff);
  987.     }
  988.     else
  989.         return((*Numof)(n - 1)); /* keep this 0-based */
  990. }
  991.  
  992. /*
  993.  * syntodisplay(n)
  994.  *
  995.  * Tranfer Syndata names to dialog boxes (Dxvoices) starting at n.
  996.  */
  997. syntodisplay(n)
  998. {
  999.     int k, r;
  1000.  
  1001.     /* for the NUMONSCREEN dialog boxes */
  1002.     for ( k=0; k<NUMONSCREEN; k++ ) {
  1003.         r = FIRSTROW+1+k;
  1004.         windgoto(r,LEFTSIDE);
  1005.         sprintf(Buff,"%-3s",vnumtext(n+k+1));
  1006.         windstr(Buff);
  1007.         windgoto(r,LEFTSIDE+6);
  1008.         windstr("                 ");
  1009.  
  1010.         /* pull the name out of the Syndata */
  1011.         windgoto(r,LEFTSIDE+6);
  1012.         windstr((*Nameof)( & (VOICEBYTE(Syndata,n+k,0) )) );
  1013.     }
  1014.     windrefresh();
  1015. }
  1016.  
  1017. /*
  1018.  * libtodisplay
  1019.  *
  1020.  * Tranfer Libdata names to the screen, starting at voice 'firstv'.
  1021.  */
  1022.  
  1023. libtodisplay(firstv)
  1024. {
  1025.     int k, r;
  1026.  
  1027.     windgoto(FIRSTROW-1,RIGHTSIDE-1);
  1028.     sprintf(Buff,"Library Voices (Bank %d)",Libbank+1);
  1029.     windstr(Buff);
  1030.  
  1031.     /* for the NUMONSCREEN dialog boxes */
  1032.     for ( k=0; k<NUMONSCREEN; k++ ) {
  1033.         r = FIRSTROW+1+k;
  1034.         windgoto(r,RIGHTSIDE);
  1035.         sprintf(Buff,"%-3s",vnumtext(firstv+k+1));
  1036.         windstr(Buff);
  1037.         windgoto(r,RIGHTSIDE+6);
  1038.         windstr("                 ");
  1039.  
  1040.         /* pull the name out of the Libdata */
  1041.         windgoto(r,RIGHTSIDE+6);
  1042.         windstr((*Nameof)(bankvoice(firstv+k)));
  1043.     }
  1044.     windrefresh();
  1045. }
  1046.  
  1047. allnotesoff()
  1048. {
  1049.     int n;
  1050.  
  1051.     /* Go through all channels. */
  1052.     for ( n=0; n<15; n++ ) {
  1053.         sendmidi(n | 0xb0);
  1054.         sendmidi(0x7b);
  1055.         sendmidi(0x00);
  1056.     }
  1057. }
  1058.  
  1059. /*
  1060.  * Below are generic edit routines, which manage a screen display
  1061.  * showing parameter values, and let you roam around and make changes.
  1062.  * The display is managed by the contents of the P array, which
  1063.  * contains the name, screen location, min/max values, etc. of
  1064.  * each parameter.
  1065.  */
  1066.  
  1067. int Prow = 0;
  1068. int Pcol = 0;
  1069. int Parm = 0;
  1070.  
  1071. /* redraw the parameter screen */
  1072. showallparms(name)
  1073. char *name;
  1074. {
  1075.     int n;
  1076.     char *s;
  1077.  
  1078.     windclear();
  1079.  
  1080.     showname(name);
  1081.     windgoto(1,0);
  1082.     for(n=strlen(name)+6;n>0;n--)
  1083.         windputc('=');
  1084.  
  1085.     /* The L array contains arbitrary screen labels */
  1086.     for ( n=0; L[n].l_text != NULL; n++ ) {
  1087.         windgoto(L[n].l_row,L[n].l_col);
  1088.         windstr(L[n].l_text);
  1089.     }
  1090.     /* Display each parameter value, and a label if there is one. */
  1091.     for ( n=0; P[n].p_name != NULL; n++ ) {
  1092.         if ( P[n].p_flags != 0 )
  1093.             continue;
  1094.         if ( (s=P[n].p_label) != NULL )
  1095.             showstr(s,P[n].p_lrow,P[n].p_lcol,0);
  1096.         showparam(n,0);
  1097.     }
  1098.     windrefresh();
  1099. }
  1100.  
  1101. showname(name)
  1102. char *name;
  1103. {
  1104.     windgoto(0,0);
  1105.     windstr("Name:                 ");
  1106.     windgoto(0,6);
  1107.     windstr(name);
  1108. }
  1109.  
  1110. showparam(n,eras)
  1111. {
  1112.     char *p;
  1113.  
  1114.     /* The p_tovis element of the P array is a function which, given */
  1115.     /* the parameter value as an argument, returns a string which is */
  1116.     /* what should be displayed on the screen. */
  1117.     p = (*(P[n].p_tovis))(P[n].p_val);
  1118.     showstr(p,P[n].p_vrow,P[n].p_vcol,eras);
  1119. }
  1120.  
  1121. showstr(p,row,col,eras)
  1122. register char *p;
  1123. register int col;
  1124. {
  1125.     register int c;
  1126.  
  1127.     windgoto(row,col);
  1128.     while ( (c=(*p++)) != '\0' ) {
  1129.         switch(c){
  1130.         case '~':
  1131.             switch( (c=(*p++)) ) {
  1132.             case 'u': row--; goto wgoto;
  1133.             case 'd': row++; goto wgoto;
  1134.             case 'l': col--; goto wgoto;
  1135.             case 'r': col++;
  1136.                 wgoto:
  1137.                 windgoto(row,col);
  1138.                 break;
  1139.             default:
  1140.                 windputc(eras?' ':c);
  1141.                 col++;
  1142.                 break;
  1143.             }
  1144.             break;
  1145.         default:
  1146.             windputc(eras?' ':c);
  1147.             col++;
  1148.             break;
  1149.         }
  1150.     }
  1151. }
  1152.  
  1153. /* Allow roaming around and changing of parameter values. */
  1154. editdata(name,data)
  1155. char *name;
  1156. char *data;    /* vmem format */
  1157. {
  1158.     int c, n;
  1159.  
  1160.     windclear();
  1161.     windrefresh();
  1162.     /* enable all the parameters */
  1163.     for ( n=0; P[n].p_name != NULL; n++ )
  1164.         enableparm(n);
  1165.  
  1166.     /* Take the voice data and put it into P */
  1167.     (*Datain)(data);
  1168.  
  1169.     Prow = Pcol = 0;
  1170.     Changed = 0;
  1171.     Redraw = 1;
  1172.     gotoparm(CH_RIGHT);    /* Get to the first parameter */
  1173.     for ( ;; ) {
  1174.         if ( Redraw ) {
  1175.             showallparms(name);
  1176.             Redraw = 0;
  1177.         }
  1178.         windgoto(Prow,Pcol);
  1179.         windrefresh();
  1180.         c = mouseorkey();
  1181.         if ( c == MOUSE ) {
  1182.             editmouse();
  1183.             continue;
  1184.         }
  1185.         switch(c){
  1186.         case CH_RIGHT:
  1187.         case CH_UP:
  1188.         case CH_DOWN:
  1189.         case CH_LEFT:
  1190.             gotoparm(c);
  1191.             break;
  1192.         case CH_REDRAW:
  1193.             showallparms(name);
  1194.             break;
  1195.         case 'N':
  1196.             /* Allow changing of voice name */
  1197.             windgoto(0,5);
  1198.             windstr("                ");
  1199.             windgoto(0,6);
  1200.             windrefresh();
  1201.             windgets(Buff);
  1202.             if ( Buff[0]!='\0' && Buff[0]!='\n' )
  1203.                 (*Setnameof)(data,Buff);
  1204.             showname(name=(*Nameof)(data));
  1205.             Changed = 1;
  1206.             break;
  1207.  
  1208.         case CH_INC:
  1209.             adjuparm(1);
  1210.             break;
  1211.         case CH_INC2:
  1212.             adjuparm(4);
  1213.             break;
  1214.         case CH_INC3:
  1215.             adjuparm(P[Parm].p_max - P[Parm].p_min);
  1216.             break;
  1217.         case CH_DEC:
  1218.             adjuparm(-1);
  1219.             break;
  1220.         case CH_DEC2:
  1221.             adjuparm(-4);
  1222.             break;
  1223.         case CH_DEC3:
  1224.             adjuparm(P[Parm].p_min - P[Parm].p_max);
  1225.             break;
  1226. #ifdef OLDSTUFF
  1227.         case 'a':
  1228.             sendaced(data);
  1229.             playnote(0);
  1230.             break;
  1231. #endif
  1232.         case ' ':
  1233.         case '\n':
  1234. #ifndef macintosh
  1235.         case '\r':
  1236. #endif
  1237.             if ( Changed ) {
  1238.                 (*Dataout)(data);
  1239.                 (*Sendedit)(data);
  1240.             }
  1241.             playnote(0);
  1242.             break;
  1243.         case '\033':
  1244.         case '`':
  1245.             allnotesoff();
  1246.             break;
  1247.         case 'q':
  1248.         case EOF:
  1249.             if ( Changed ) {
  1250.                 (*Dataout)(data);
  1251.                 (*Sendedit)(data);
  1252.             }
  1253.             return;
  1254.         default:
  1255.             break;
  1256.         }
  1257.     }
  1258. }
  1259.  
  1260. adjuparm(incdec)
  1261. {
  1262.     int v, n;
  1263.  
  1264.     v = P[Parm].p_val + incdec;
  1265.     if ( v < (n=P[Parm].p_min) )
  1266.         v = n;
  1267.     if ( v > (n=P[Parm].p_max) )
  1268.         v = n;
  1269.     Changed = 1;
  1270.     showparam(Parm,1);    /* erase the old val */
  1271.     P[Parm].p_val = v;
  1272.     showparam(Parm,0);    /* show the new val */
  1273. }
  1274.  
  1275. editmouse()
  1276. {
  1277.     int row, col, thisparm;
  1278.  
  1279.     getmouse(&row,&col);
  1280.     thisparm = closeparm(row,col);
  1281.     if ( thisparm == Parm ) {
  1282.         if ( statmouse() > 1 )
  1283.             adjuparm(-1);    /* right button */
  1284.         else if ( statmouse() == 1 ) /* added by mab - bug fix */
  1285.             adjuparm(1);    /* left button */
  1286.     }
  1287.     else {
  1288.         Parm = thisparm;
  1289.         Prow = P[Parm].p_vrow;
  1290.         Pcol = P[Parm].p_vcol;
  1291.     }
  1292. }
  1293.  
  1294. /* closeparm - Find the closest parameter */
  1295. closeparm(row,col)
  1296. {
  1297.     register struct paraminfo *pp;
  1298.     register int n;
  1299.     int dist, mindist, minparm, dr, dc;
  1300.  
  1301.     minparm = 0;
  1302.     mindist = Rows + Cols;
  1303.     for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) {
  1304.         if ( pp->p_flags != 0 )
  1305.             continue;
  1306.         if ( (dr=row-(pp->p_vrow)) < 0 )
  1307.             dr = -dr;
  1308.         if ( (dc=col-(pp->p_vcol)) < 0 )
  1309.             dc = -dc;
  1310.         if ( (dist=dr*dr+dc*dc) < mindist ) {
  1311.             minparm = n;
  1312.             mindist = dist;
  1313.         }
  1314.     }
  1315.     return(minparm);
  1316. }
  1317.  
  1318. /* playnote - play the 'auto' note */
  1319. playnote(i)
  1320. {
  1321.     int pitch, vol, dur, chan;
  1322.     long endtime;
  1323.  
  1324.     pitch = getval("autopitch");
  1325.     if(i == 0) { /* called from inside edit-mode */
  1326.         chan = getval("autochan");
  1327.     } else { /* called from the top level */
  1328.         chan = Channel;
  1329.     }
  1330.     vol = getval("autovol");
  1331.     dur = getval("autodur");
  1332.     endtime = milliclock() + dur * 100;
  1333.     midinote(1,chan,pitch,vol);
  1334.     while ( milliclock() < endtime )
  1335.         ;
  1336.     midinote(0,chan,pitch,vol);
  1337. }
  1338.  
  1339. /* gotoparm - search for the next parameter in the specified direction */
  1340. gotoparm(dir)
  1341. {
  1342.     int n, k, inc, pm, orig, r = Prow, c = Pcol;
  1343.  
  1344.     if ( dir==CH_LEFT || dir==CH_RIGHT ) {
  1345.         if ( dir==CH_LEFT )
  1346.             c--;
  1347.         else
  1348.             c++;
  1349.         orig = c;
  1350.         inc = 0;
  1351.         pm = -1;
  1352.         /* look up and down, alternately */
  1353.         for ( n=2*Rows; n>0; n-- ) {
  1354.             r += (pm * inc++);
  1355.             pm = -pm;
  1356.             if ( r < 0 || r >= Rows )
  1357.                 continue;
  1358.             if ( dir == CH_LEFT ) {
  1359.                 for ( c=orig; c>=0; c-- ) {
  1360.                     if ( parmat(r,c) )
  1361.                         return;
  1362.                 }
  1363.             }
  1364.             else {
  1365.                 for ( c=orig; c<Cols; c++ ) {
  1366.                     if ( parmat(r,c) )
  1367.                         return;
  1368.                 }
  1369.             }
  1370.         }
  1371.         return;
  1372.     }
  1373.     if ( dir==CH_DOWN || dir==CH_UP ) {
  1374.         if ( dir==CH_DOWN )
  1375.             r++;
  1376.         else
  1377.             r--;
  1378.         orig = c;
  1379.         while ( r >= 0 && r < Rows ) {
  1380.             /* look toward both sides at the same time */
  1381.             inc = 0;
  1382.             pm = -1;
  1383.             for ( k=2*Cols; k>0; k-- ) {
  1384.                 c += (pm * inc++);
  1385.                 pm = -pm;
  1386.                 if ( c < 0 || c >= Cols )
  1387.                     continue;
  1388.                 if ( parmat(r,c) )
  1389.                     return;
  1390.             }
  1391.             if ( dir==CH_DOWN )
  1392.                 r++;
  1393.             else
  1394.                 r--;
  1395.             c = orig;
  1396.         }
  1397.         return;
  1398.     }
  1399. }
  1400.  
  1401. /* paramat - return non-zero if a parameter value is at position r,c */
  1402. parmat(r,c)
  1403. register int r, c;
  1404. {
  1405.     register int n;
  1406.     register struct paraminfo *pp;
  1407.  
  1408.     for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) {
  1409.         if ( pp->p_flags != 0 )
  1410.             continue;
  1411.         if ( pp->p_vrow==r && pp->p_vcol==c ) {
  1412.             Prow = r;
  1413.             Pcol = c;
  1414.             Parm = n;
  1415.             return(1);
  1416.         }
  1417.     }
  1418.     return(0);
  1419. }
  1420.  
  1421. /* parmindex - return index (in P) of a given parameter name. */
  1422. parmindex(name)
  1423. char *name;
  1424. {
  1425.     int n;
  1426.     char *s;
  1427.  
  1428.     for ( n=0; (s=P[n].p_name) != NULL; n++ ) {
  1429.         if ( strcmp(s,name) == 0 )
  1430.             return(n);
  1431.     }
  1432.     sprintf(Buff,"HEY, PARMINDEX(%s) NOT FOUND!",name);
  1433.     windstr(Buff);
  1434.     windrefresh();
  1435.     return(-1);
  1436. }
  1437.  
  1438. setval(name,v)
  1439. char *name;
  1440. {
  1441.     int n;
  1442.  
  1443.     if ( (n=parmindex(name)) < 0 )
  1444.         return;
  1445.     P[n].p_val = v;
  1446. }
  1447.  
  1448. getval(name)
  1449. char *name;
  1450. {
  1451.     int n;
  1452.  
  1453.     if ( (n=parmindex(name)) < 0 )
  1454.         return(0);
  1455.     return(P[n].p_val);
  1456. }
  1457.  
  1458. enableparm(n)
  1459. {
  1460.     if ( P[n].p_flags != 0 )
  1461.         P[n].p_flags = 0;
  1462. }
  1463.  
  1464. disableparm(n)
  1465. {
  1466.     if ( P[n].p_flags == 0 )
  1467.         P[n].p_flags = 1;
  1468. }
  1469.  
  1470. midinote(onoff,chan,pitch,vol)
  1471. {
  1472.     sendmidi( ((onoff==1)?(0x90):(0x80)) | ((chan-1)&0xf) );
  1473.     sendmidi( pitch & 0x7f );
  1474.     sendmidi( vol & 0x7f );
  1475. }
  1476.  
  1477. static char Nbuff[16];
  1478.  
  1479. char *visnum(v)
  1480. {
  1481.     sprintf(Nbuff,"%d",v);
  1482.     return(Nbuff);
  1483. }
  1484. char *visonoff(v)
  1485. {
  1486.     if ( v==0 )
  1487.         return("off");
  1488.     else
  1489.         return("on");
  1490. }
  1491.  
  1492. char *
  1493. bankvoice(voice)
  1494. {
  1495.     int offset = Libbank * Nvoices * Voicesize + voice * Voicesize;
  1496.     return(Libdata + offset);
  1497. }
  1498. SHAR_EOF
  1499. cat << \SHAR_EOF > yama_com.c
  1500. /*
  1501.  * GLIB - a Generic LIBrarian and editor for synths
  1502.  *
  1503.  * Yamaha Common Routines
  1504.  */
  1505.  
  1506. #define OVERLAY1
  1507.  
  1508. #include "glib.h"
  1509. #include <ctype.h>
  1510.  
  1511. #define DX100VSIZE 128
  1512. #define DX100NSIZE 17
  1513.  
  1514. char *visnum(), *visonoff(), *vism3num(), *viswave(), *vismono();
  1515. char *visfreq(), *visdx1a();
  1516. extern int Tx81;
  1517.  
  1518. int *txindex = NULL;
  1519. int txleng = 0;
  1520.  
  1521.  
  1522. extern int Dopmap[];
  1523.  
  1524. int Tx81 = 0;    /* 1 means we're talking to the TX81Z */
  1525. int Dopmap[] = { 3,1,2,0 };
  1526.  
  1527. int txfreq[] = {
  1528. 50, 56, 62, 69, 75, 81, 87, 93,
  1529.      100, 106, 112, 118, 124, 131, 137, 143,
  1530. 71, 80, 88, 97, 106, 115, 123, 132,
  1531.      141, 149, 158, 167, 176, 184, 193, 202,
  1532. 78, 88, 98, 107, 117, 127, 137, 147,
  1533.      156, 166, 176, 186, 196, 205, 215, 225,
  1534. 87, 98, 108, 119, 130, 141, 151, 162,
  1535.      173, 183, 194, 205, 216, 226, 237, 248,
  1536. 100, 106, 112, 119, 125, 131, 137, 143,
  1537.      149, 156, 162, 168, 174, 180, 187, 193,
  1538. 141, 150, 159, 167, 176, 185, 194, 203,
  1539.      211, 220, 229, 238, 247, 255, 264, 273,
  1540. 157, 167, 177, 186, 196, 206, 216, 226,
  1541.      235, 245, 255, 265, 275, 284, 294, 304,
  1542. 173, 184, 195, 205, 216, 227, 238, 249,
  1543.      259, 270, 281, 292, 303, 313, 324, 335,
  1544. 200, 206, 212, 218, 225, 231, 237, 243,
  1545.      249, 256, 262, 268, 274, 280, 287, 293,
  1546. 282, 291, 300, 308, 317, 326, 335, 344,
  1547.      352, 361, 370, 379, 388, 396, 405, 414,
  1548. 300, 306, 312, 318, 325, 331, 337, 343,
  1549.      349, 356, 362, 368, 374, 380, 387, 393,
  1550. 314, 324, 334, 343, 353, 363, 373, 383,
  1551.      392, 402, 412, 422, 432, 441, 451, 461,
  1552. 346, 357, 368, 378, 389, 400, 411, 422,
  1553.      432, 443, 454, 465, 476, 486, 497, 508,
  1554. 400, 406, 412, 418, 425, 431, 437, 443,
  1555.      449, 456, 462, 468, 474, 480, 487, 493,
  1556. 424, 433, 441, 450, 459, 468, 476, 485,
  1557.      494, 503, 511, 520, 529, 537, 546, 555,
  1558. 471, 481, 491, 500, 510, 520, 530, 539,
  1559.      549, 559, 569, 579, 588, 598, 608, 618,
  1560. 500, 506, 512, 519, 525, 531, 537, 543,
  1561.      550, 556, 562, 568, 574, 581, 587, 593,
  1562. 519, 530, 540, 551, 562, 573, 584, 594,
  1563.      605, 616, 627, 638, 648, 659, 670, 681,
  1564. 565, 574, 582, 591, 600, 609, 617, 626,
  1565.      635, 644, 652, 661, 670, 678, 687, 696,
  1566. 600, 606, 612, 619, 625, 631, 637, 643,
  1567.      650, 656, 662, 668, 674, 681, 687, 693,
  1568. 628, 638, 647, 657, 667, 677, 687, 696,
  1569.      706, 716, 726, 736, 745, 755, 765, 775,
  1570. 692, 703, 713, 724, 735, 746, 757, 767,
  1571.      778, 789, 800, 811, 821, 832, 843, 854,
  1572. 700, 706, 712, 719, 725, 731, 737, 743,
  1573.      750, 756, 762, 768, 774, 781, 787, 793,
  1574. 707, 716, 724, 733, 742, 750, 759, 768,
  1575.      776, 785, 794, 802, 811, 820, 828, 837,
  1576. 785, 795, 804, 814, 824, 834, 844, 853,
  1577.      863, 873, 883, 893, 902, 912, 922, 932,
  1578. 800, 806, 812, 819, 825, 831, 837, 843,
  1579.      850, 856, 862, 868, 874, 881, 887, 893,
  1580. 848, 857, 865, 874, 883, 891, 900, 909,
  1581.      917, 926, 935, 943, 952, 961, 969, 978,
  1582. 865, 876, 886, 897, 908, 919, 930, 940,
  1583.      951, 962, 973, 984, 994, 1005, 1016, 1027,
  1584. 900, 906, 912, 919, 925, 931, 937, 943,
  1585.      950, 956, 962, 968, 974, 981, 987, 993,
  1586. 942, 952, 961, 971, 981, 991, 1001, 1010,
  1587.      1020, 1030, 1040, 1050, 1059, 1069, 1079, 1089,
  1588. 989, 998, 1006, 1015, 1024, 1032, 1041, 1050,
  1589.      1058, 1067, 1076, 1084, 1093, 1102, 1110, 1119,
  1590. 1000, 1006, 1012, 1019, 1025, 1031, 1037, 1043,
  1591.      1050, 1056, 1062, 1068, 1074, 1081, 1087, 1093,
  1592. 1038, 1049, 1060, 1070, 1081, 1092, 1103, 1113,
  1593.      1124, 1135, 1146, 1157, 1167, 1178, 1189, 1200,
  1594. 1099, 1109, 1119, 1128, 1138, 1148, 1158, 1167,
  1595.      1177, 1187, 1197, 1207, 1216, 1226, 1236, 1246,
  1596. 1100, 1106, 1112, 1119, 1125, 1131, 1137, 1143,
  1597.      1150, 1156, 1162, 1168, 1174, 1181, 1187, 1193,
  1598. 1130, 1139, 1147, 1156, 1165, 1173, 1182, 1191,
  1599.      1199, 1208, 1217, 1225, 1234, 1243, 1251, 1260,
  1600. 1200, 1206, 1212, 1219, 1225, 1231, 1237, 1243,
  1601.      1250, 1256, 1262, 1268, 1274, 1281, 1287, 1293,
  1602. 1211, 1222, 1233, 1243, 1254, 1265, 1276, 1286,
  1603.      1297, 1308, 1319, 1330, 1340, 1351, 1362, 1373,
  1604. 1256, 1266, 1276, 1285, 1295, 1305, 1315, 1324,
  1605.      1334, 1344, 1354, 1364, 1373, 1383, 1393, 1403,
  1606. 1272, 1281, 1289, 1298, 1306, 1315, 1323, 1332,
  1607.      1341, 1349, 1358, 1366, 1375, 1384, 1392, 1401,
  1608. 1300, 1306, 1312, 1319, 1325, 1331, 1337, 1343,
  1609.      1350, 1356, 1362, 1368, 1374, 1381, 1387, 1393,
  1610. 1384, 1395, 1406, 1416, 1427, 1438, 1449, 1459,
  1611.      1470, 1481, 1492, 1503, 1513, 1524, 1535, 1546,
  1612. 1400, 1406, 1412, 1419, 1425, 1431, 1437, 1443,
  1613.      1450, 1456, 1462, 1468, 1474, 1481, 1487, 1493,
  1614. 1410, 1419, 1428, 1436, 1445, 1454, 1463, 1471,
  1615.      1480, 1489, 1498, 1507, 1515, 1524, 1533, 1542,
  1616. 1413, 1423, 1433, 1442, 1452, 1462, 1472, 1481,
  1617.      1491, 1501, 1511, 1521, 1530, 1540, 1550, 1560,
  1618. 1500, 1506, 1512, 1519, 1525, 1531, 1537, 1543,
  1619.      1550, 1556, 1562, 1568, 1574, 1581, 1587, 1593,
  1620. 1555, 1563, 1572, 1581, 1589, 1598, 1606, 1615,
  1621.      1623, 1632, 1640, 1649, 1657, 1666, 1674, 1683,
  1622. 1557, 1568, 1579, 1589, 1600, 1611, 1622, 1632,
  1623.      1643, 1654, 1665, 1676, 1686, 1697, 1708, 1719,
  1624. 1570, 1580, 1590, 1599, 1609, 1619, 1629, 1638,
  1625.      1648, 1658, 1668, 1678, 1687, 1697, 1707, 1717,
  1626. 1696, 1704, 1713, 1722, 1730, 1739, 1747, 1756,
  1627.      1764, 1773, 1781, 1790, 1798, 1807, 1815, 1824,
  1628. 1727, 1737, 1747, 1756, 1766, 1776, 1786, 1795,
  1629.      1805, 1815, 1825, 1835, 1844, 1854, 1864, 1874,
  1630. 1730, 1741, 1752, 1762, 1773, 1784, 1795, 1805,
  1631.      1816, 1827, 1838, 1849, 1859, 1870, 1881, 1892,
  1632. 1837, 1845, 1854, 1863, 1871, 1880, 1888, 1897,
  1633.      1905, 1914, 1922, 1931, 1939, 1948, 1956, 1965,
  1634. 1884, 1894, 1904, 1913, 1923, 1933, 1943, 1952,
  1635.      1962, 1972, 1982, 1992, 2001, 2011, 2021, 2031,
  1636. 1903, 1914, 1925, 1935, 1946, 1957, 1968, 1978,
  1637.      1989, 2000, 2011, 2022, 2032, 2043, 2054, 2065,
  1638. 1978, 1986, 1995, 2004, 2012, 2021, 2029, 2038,
  1639.      2046, 2055, 2063, 2072, 2080, 2089, 2097, 2106,
  1640. 2041, 2051, 2061, 2070, 2080, 2090, 2100, 2110,
  1641.      2119, 2129, 2139, 2149, 2159, 2168, 2178, 2188,
  1642. 2076, 2087, 2098, 2108, 2119, 2130, 2141, 2152,
  1643.      2162, 2173, 2184, 2195, 2206, 2216, 2227, 2238,
  1644. 2120, 2128, 2137, 2145, 2154, 2162, 2171, 2179,
  1645.      2188, 2196, 2205, 2213, 2222, 2230, 2238, 2247,
  1646. 2198, 2208, 2218, 2227, 2237, 2247, 2257, 2267,
  1647.      2276, 2286, 2296, 2306, 2316, 2325, 2335, 2345,
  1648. 2249, 2260, 2271, 2281, 2292, 2303, 2314, 2325,
  1649.      2335, 2346, 2357, 2368, 2379, 2389, 2400, 2411,
  1650. 2355, 2365, 2375, 2384, 2394, 2404, 2414, 2424,
  1651.      2433, 2443, 2453, 2463, 2473, 2482, 2492, 2502,
  1652. 2422, 2433, 2444, 2454, 2465, 2476, 2487, 2498,
  1653.      2508, 2519, 2530, 2541, 2552, 2562, 2573, 2584,
  1654. 2595, 2606, 2617, 2627, 2638, 2649, 2660, 2671,
  1655.      2681, 2692, 2703, 2714, 2725, 2735, 2746, 2757
  1656. };
  1657.  
  1658. /*
  1659.  * dxtxdin
  1660.  *
  1661.  * Take info from 'data' and stuff values in the P array, by using
  1662.  * the setval (and setopval) functions.  'data' is the Yamaha VMEM format.
  1663.  * This function works for both the dx100 and tx81z.
  1664.  */
  1665.  
  1666. dxtxdin(data)
  1667. char *data;
  1668. {
  1669.     int dop, adop, n, crs, fin, v;
  1670.  
  1671.     setdxtx();
  1672.     if ( Tx81 )
  1673.         txinit();
  1674.     for ( n=1; n<=4; n++ ) {
  1675.         dop = Dopmap[n-1]*10;
  1676.         adop = Dopmap[n-1]*2;
  1677.         setopval(n,"attack",data[0+dop]);
  1678.         setopval(n,"decay1",data[1+dop]);
  1679.         setopval(n,"level1",data[4+dop]);
  1680.         setopval(n,"decay2",data[2+dop]);
  1681.         setopval(n,"release",data[3+dop]);
  1682.         setopval(n,"keyscale",data[5+dop]);
  1683.         setopval(n,"ampmod",(data[6+dop]>>6)&01);
  1684.         setopval(n,"egbias",(data[6+dop]>>3)&07);
  1685.         setopval(n,"velocity",data[6+dop]&07);
  1686.         setopval(n,"outlevel",data[7+dop]);
  1687.  
  1688.         if ( Tx81 ) {
  1689.             crs = data[8+dop];
  1690.             fin = (data[74+adop]) & 017;
  1691.             v = freqin(crs,fin);
  1692.             setopval(n,"freq",v);
  1693.         }
  1694.         else
  1695.             setopval(n,"freq",data[8+dop]);
  1696.  
  1697.         setopval(n,"keyrate",data[9+dop]>>3);
  1698.         setopval(n,"detune",data[9+dop]&07);
  1699.  
  1700.         if ( Tx81 ) {
  1701.             setopval(n,"egsft",(data[73+adop]>>4)&03);
  1702.             setopval(n,"fix",(data[73+adop]>>3)&01);
  1703.             setopval(n,"wave",(data[74+adop]>>4)&07);
  1704.         }
  1705.     }
  1706.     setval("lfosync",(data[40]>>6)&01);
  1707.     setval("feedback",(data[40]>>3)&07);
  1708.     setval("algorithm",data[40]&07);
  1709.     setval("lfospeed",data[41]);
  1710.     setval("lfodelay",data[42]);
  1711.     setval("pmoddepth",data[43]);
  1712.     setval("amoddepth",data[44]);
  1713.     setval("pmodsens",(data[45]>>4)&07);
  1714.     setval("amodsens",(data[45]>>2)&03);
  1715.     setval("lfowave",data[45]&03);
  1716.     setval("transpose",data[46]);
  1717.     setval("pitchbend",data[47]);
  1718.     setval("portatime",data[49]);
  1719.     setval("modprange",data[51]);
  1720.     setval("modarange",data[52]);
  1721.     setval("breathprange",data[53]);
  1722.     setval("breatharange",data[54]);
  1723.     setval("breathpbias",data[55]);
  1724.     setval("breathegbias",data[56]);
  1725.     setval("playmode",(data[48]>>3)&01);
  1726.     setval("susfoot",(data[48]>>2)&01);
  1727.     setval("portfoot",(data[48]>>1)&01);
  1728.     setval("portmode",data[48]&01);
  1729.     setval("autochan",Channel);
  1730.     if ( Tx81 ) {
  1731.         setval("reverbrate",data[81]&07);
  1732.         setval("fcpitch",data[82]);
  1733.         setval("fcamp",data[83]);
  1734.     }
  1735. }
  1736.  
  1737. /*
  1738.  * dxtxdout
  1739.  *
  1740.  * Take (possibly changed) parameters values out of the P array and
  1741.  * put them back into 'data'.  'data' is in the Yamaha VMEM format.
  1742.  * This works for both the dx100 and tx81z.
  1743.  */
  1744.  
  1745. dxtxdout(data)
  1746. char *data;
  1747. {
  1748.     int dop, n, crs, fin;
  1749.  
  1750.     for ( n=1; n<=4; n++ ) {
  1751.         dop = Dopmap[n-1]*10;
  1752.         data[0+dop] = getopval(n,"attack");
  1753.         data[1+dop] = getopval(n,"decay1");
  1754.         data[4+dop] = getopval(n,"level1");
  1755.         data[2+dop] = getopval(n,"decay2");
  1756.         data[3+dop] = getopval(n,"release");
  1757.         data[5+dop] = getopval(n,"keyscale");
  1758.         data[6+dop] = getopval(n,"ampmod")<<6
  1759.                 | getopval(n,"egbias")<<3
  1760.                 | getopval(n,"velocity");
  1761.         data[7+dop] = getopval(n,"outlevel");
  1762.         data[9+dop] = getopval(n,"keyrate")<<3 | getopval(n,"detune");
  1763.  
  1764.         if ( ! Tx81 ) {
  1765.             data[8+dop] = getopval(n,"freq");
  1766.         }
  1767.         else {
  1768.             freqout(getopval(n,"freq"),&crs,&fin);
  1769.             data[8+dop] = crs;
  1770.  
  1771.             dop = Dopmap[n-1]*2;
  1772.             data[73+dop] = getopval(n,"egsft")<<4
  1773.                     | getopval(n,"fix")<<3
  1774.                     /* | getopval(n,"fixrg") */;
  1775.             data[74+dop] = getopval(n,"wave")<<4 | fin;
  1776.         }
  1777.     }
  1778.     data[40] = getval("lfosync")<<6
  1779.         | getval("feedback")<<3
  1780.         | getval("algorithm");
  1781.     data[41] = getval("lfospeed");
  1782.     data[42] = getval("lfodelay");
  1783.     data[43] = getval("pmoddepth");
  1784.     data[44] = getval("amoddepth");
  1785.     data[45] = getval("pmodsens")<<4 | getval("amodsens")<<2
  1786.         | getval("lfowave");
  1787.     data[46] = getval("transpose");
  1788.     data[47] = getval("pitchbend");
  1789.     data[49] = getval("portatime");
  1790.     data[51] = getval("modprange");
  1791.     data[52] = getval("modarange");
  1792.     data[53] = getval("breathprange");
  1793.     data[54] = getval("breatharange");
  1794.     data[55] = getval("breathpbias");
  1795.     data[56] = getval("breathegbias");
  1796.     data[48] = (unsigned) ( getval("playmode")<<3
  1797.         | getval("susfoot")<<2
  1798.         | getval("portfoot")<<1
  1799.         | getval("portmode"));
  1800.  
  1801.     if ( Tx81 ) {
  1802.         data[81] = getval("reverbrate");
  1803.         data[82] = getval("fcpitch");
  1804.         data[83] = getval("fcamp");
  1805.     }
  1806.  
  1807.     Channel = getval("autochan");
  1808. }
  1809.  
  1810. setdxtx()
  1811. {
  1812.     if ( strcmp(Synthname,"DX-100")==0 )
  1813.         Tx81 = 0;
  1814.     else
  1815.         Tx81 = 1;
  1816. }
  1817.  
  1818. setopval(n,str,v)
  1819. char *str;
  1820. {
  1821.     char buff[32];
  1822.     sprintf(buff,"op%d%s",n,str);
  1823.     setval(buff,v);
  1824. }
  1825.  
  1826. getopval(n,str)
  1827. char *str;
  1828. {
  1829.     char buff[32];
  1830.     sprintf(buff,"op%d%s",n,str);
  1831.     return(getval(buff));
  1832. }
  1833.  
  1834. /*
  1835.  * The routines below are used (in the P array) for printing the
  1836.  * values of various parameters (e.g. the vism3num routine prints
  1837.  * the value-3, which is appropriate for the 'detune' parameter.
  1838.  */
  1839.  
  1840. char Numbuff[8];
  1841.  
  1842. char *visnum();
  1843.  
  1844. char *
  1845. vis1num(v)
  1846. {
  1847.     sprintf(Numbuff,"%d",v+1);
  1848.     return(Numbuff);
  1849. }
  1850.  
  1851. char *
  1852. vism3num(v)
  1853. {
  1854.     sprintf(Numbuff,"%d",v-3);
  1855.     return(Numbuff);
  1856. }
  1857.  
  1858. char *visonoff();
  1859.  
  1860. char *
  1861. vismono(v)
  1862. {
  1863.     if ( v==0 )
  1864.         return("poly");
  1865.     else
  1866.         return("mono");
  1867. }
  1868.  
  1869. /*
  1870.             4    2  4    2         4                             4
  1871.             |    |  |    |         |               4             |
  1872.         2---3    ---3    3  4   2  3   1  4     ___|___    1  2  3
  1873.         |           |    |  |   |  |   |  |     |  |  |    |__|__|
  1874.         1           1    1---   1---   2  3     1  2  3
  1875.                                        |__|     |__|__|
  1876.                                                              1  2  3  4
  1877.                                                              |__|__|__|
  1878.  */
  1879.  
  1880. char *Algostr[] = {
  1881.     "1     ~d2---3~u~l|~u~l4~d~d~d~l~l~l~l~l|~l~d1",
  1882.     "2     ~d---3~l~l~l~l~u|  |~l~l~l~l~u2  4~l~d~d~d|~l~d1",
  1883.     "3     ~d3  4~l~l~l~l~u|~l~u2~l~d~d~d|  |~d~l~l~l~l1---",
  1884.     "4     ~d2  3~l~u|~u~l4~l~d~d~d~l~l~l|  |~l~l~l~l~d1---",
  1885.     "5     ~d~u1  4~d~l~l~l~l|  |~d~l~l~l~l2  3~d~l~l~l~l----",
  1886.     "6     ~d|  |  |~u~l~l~l~l~l~l~l___|___~u~l~l~l~l4~l~d~d~d~l~l~l1  2  3~d~l~l~l~l~l~l~l|__|__|",
  1887.     "7     ~d1  2  3~u~l|~u~l4~l~d~d~d~l~l~l~l~l~l|__|__|",
  1888.     "8     ~d1  2  3  4~d~l~l~l~l~l~l~l~l~l~l|__|__|__|"
  1889. };
  1890.  
  1891. char *
  1892. visdx1a(v)
  1893. {
  1894.     if ( v >= 0 && v <= 7 )
  1895.         return(Algostr[v]);
  1896.     else
  1897.         return("????");
  1898. }
  1899.  
  1900. char *
  1901. viswave(v)
  1902. {
  1903.     switch(v){
  1904.     case 0: return("saw up");
  1905.     case 1: return("square");
  1906.     case 2: return("triangle");
  1907.     case 3: return("s/hold");
  1908.     default: return("???");
  1909.     }
  1910. }
  1911.  
  1912. char *Freqstr[] = {    /* values from 0 to 63 */
  1913.     "0.50 ", "0.71 ", "0.78 ", "0.87 ", "1.00 ",
  1914.     "1.41 ", "1.57 ", "1.73 ", "2.00 ", "2.82 ",
  1915.     "3.00 ", "3.14 ", "3.46 ", "4.00 ", "4.24 ",
  1916.     "4.71 ", "5.00 ", "5.19 ", "5.65 ", "6.00 ",
  1917.     "6.28 ", "6.92 ", "7.00 ", "7.07 ", "7.85 ",
  1918.     "8.00 ", "8.48 ", "8.65 ", "9.00 ", "9.42 ",
  1919.     "9.89 ", "10.00", "10.38", "10.99", "11.00",
  1920.     "11.30", "12.00", "12.11", "12.56", "12.72",
  1921.     "13.00", "13.84", "14.00", "14.10", "14.13",
  1922.     "15.00", "15.55", "15.57", "15.70", "16.96",
  1923.     "17.27", "17.30", "18.37", "18.84", "19.03",
  1924.     "19.78", "20.41", "20.76", "21.20", "21.98",
  1925.     "22.49", "23.55", "24.22", "25.95"
  1926. };
  1927.  
  1928. char *
  1929. visfreq(v)
  1930. {
  1931.     if ( v >=0 && v <= 63 )
  1932.         return ( Freqstr[v] );
  1933.     else
  1934.         return("????");
  1935. }
  1936.  
  1937. /*
  1938.  * dx1sedit
  1939.  *
  1940.  * Send a single voice to the edit buffer of the DX.
  1941.  */
  1942. dx1sedit(data)
  1943. char *data;
  1944. {
  1945.     setdxtx();
  1946.     if ( Tx81 )
  1947.         sendaced(data);
  1948.     sendvced(data);
  1949. }
  1950.  
  1951. sendvced(data)
  1952. char *data;
  1953. {
  1954.     char vdata[DX100VSIZE];
  1955.     int n, cksum, c;
  1956.  
  1957.     clrdata(vdata,DX100VSIZE);
  1958.     vmemtovced(data,vdata);
  1959.     sendmidi(0xf0);
  1960.     sendmidi(0x43);
  1961.     sendmidi(Channel-1);    /* channel # */
  1962.     sendmidi(0x03);        /* format type */
  1963.     sendmidi(0x00);        /* byte count */
  1964.     sendmidi(0x5d);        /* byte count */
  1965.     cksum = 0;
  1966.     for ( n=0; n<93; n++ ) {
  1967.         sendmidi(c = (int)(vdata[n]));
  1968.         cksum += c;
  1969.     }
  1970.     sendmidi((-cksum) & 0x7f);
  1971.     sendmidi(EOX);
  1972. }
  1973.  
  1974. sendaced(data)
  1975. char *data;
  1976. {
  1977.     char *p, vdata[DX100VSIZE];
  1978.     int n, cksum, c;
  1979.  
  1980.     clrdata(vdata,DX100VSIZE);
  1981.     vmemtoaced(data,vdata);
  1982.     sendmidi(0xf0);
  1983.     sendmidi(0x43);
  1984.     sendmidi(Channel-1);    /* channel # */
  1985.     sendmidi(0x7e);        /* format type */
  1986.     sendmidi(0x00);        /* byte count */
  1987.     sendmidi(0x21);        /* byte count */
  1988.     p = "LM  8976AE";
  1989.     cksum = 0;
  1990.     while ( (c=(int)(*p++)) != '\0' ) {
  1991.         sendmidi(c);
  1992.         cksum += c;
  1993.     }
  1994.     for ( n=0; n<23; n++ ) {
  1995.         sendmidi(c=(int)(vdata[n]));
  1996.         cksum += c;
  1997.     }
  1998.     sendmidi((-cksum) & 0x7f);
  1999.     sendmidi(EOX);
  2000. }
  2001.  
  2002. /*
  2003.  * vmemtovced
  2004.  *
  2005.  * convert a vmem format voice to vced format.
  2006.  */
  2007.  
  2008. vmemtovced(data,vdata)
  2009. char *data;
  2010. char *vdata;
  2011. {
  2012.     int vop, dop, n;
  2013.  
  2014.     for ( n=0; n<4; n++ ) {
  2015.         /* vop = Dopmap[n]*13; */
  2016.         vop = Dopmap[n]*13;
  2017.         dop = Dopmap[n]*10;
  2018.         vdata[vop+0] = data[dop+0];    /* attack rate */
  2019.         vdata[vop+1] = data[dop+1];    /* decay 1 rate */
  2020.         vdata[vop+2] = data[dop+2];    /* decay 2 rate */
  2021.         vdata[vop+3] = data[dop+3];    /* release rate */
  2022.         vdata[vop+4] = data[dop+4];    /* decal 1 level */
  2023.         vdata[vop+5] = data[dop+5];    /* keyboard scaling level */
  2024.         vdata[vop+6] = (data[dop+9]>>3);/* keyboard scaling rate */
  2025.         vdata[vop+7] = (data[dop+6]>>3)&7;    /* eg bias sens. */
  2026.         vdata[vop+8] = (data[dop+6]>>6)&1;    /* amp. mod. enable */
  2027.         vdata[vop+9] = (data[dop+6]&7);    /* key velocity */
  2028.         vdata[vop+10] = data[dop+7];    /* output level */
  2029.         vdata[vop+11] = data[dop+8];    /* osc. frequency */
  2030.         vdata[vop+12] = (data[dop+9]&7);    /* detune */
  2031.     }
  2032.     vdata[52] = (data[40]&7);    /* algorithm */
  2033.     vdata[53] = (data[40]>>3)&7;    /* feedback level */
  2034.     vdata[54] = data[41];        /* lfo speed */
  2035.     vdata[55] = data[42];        /* lfo delay */
  2036.     vdata[56] = data[43];        /* pitch modulation depth */
  2037.     vdata[57] = data[44];        /* amplitude modulation depth */
  2038.     vdata[58] = (data[40]>>6)&1;    /* lfo sync */
  2039.     vdata[59] = data[45]&3;        /* lfo wave */
  2040.     vdata[60] = (data[45]>>4)&7;        /* pitch modulation sens. */
  2041.     vdata[61] = (data[45]>>2)&3;        /* amp. modulation sens. */
  2042.     vdata[62] = data[46];        /* transpose */
  2043.     vdata[63] = (data[48]>>3)&1;    /* play mode (poly/mono) */
  2044.     vdata[64] = data[47];        /* pitch bend range */
  2045.     vdata[65] = (data[48]&1);    /* portamento mode */
  2046.     vdata[66] = data[49];        /* portamento time */
  2047.     vdata[67] = data[50];        /* foot volume range */
  2048.     vdata[68] = (data[48]>>2)&1;    /* sustain foot switch */
  2049.     vdata[69] = (data[48]>>1)&1;    /* portamento foot switch */
  2050.     vdata[70] = (data[48]>>4)&1;    /* chorus switch */
  2051.     vdata[71] = data[51];        /* mod. wheel pitch mod. range */
  2052.     vdata[72] = data[52];        /* mod. wheel ampli. mod. range */
  2053.     vdata[73] = data[53];        /* breath pitch mod. range */
  2054.     vdata[74] = data[54];        /* breath ampli. mod. range */
  2055.     vdata[75] = data[55];        /* breath control pitch bias range */
  2056.     vdata[76] = data[56];        /* breath control EG bias range */
  2057.     for ( n=77; n<93; n++ )        /* voice name AND pitch EG rates */
  2058.         vdata[n] = data[n-20];
  2059. }
  2060.  
  2061. /*
  2062.  * vmemtoaced
  2063.  *
  2064.  * Convert a vmem format voice to aced format (TX81Z).
  2065.  */
  2066.  
  2067. vmemtoaced(data,adata)
  2068. char *data;
  2069. char *adata;
  2070. {
  2071.     int vop, aop, n;
  2072.  
  2073.     for ( n=0; n<4; n++ ) {
  2074.         vop = 73 + Dopmap[n]*2;
  2075.         aop = Dopmap[n]*5;
  2076.         adata[0+aop] = (data[vop]>>3) & 01;    /* fixed freq (0,1) */
  2077.         adata[1+aop] = data[vop] & 07;       /* fixed freq range (0-7) */
  2078.         adata[2+aop] = data[vop+1] & 017;       /* freq range fine (0-15) */
  2079.         adata[3+aop] = (data[vop+1]>>4) & 07;  /* op. waveform (0-7) */
  2080.         adata[4+aop] = (data[vop]>>3) & 03;   /* EG shift (0-3) */
  2081.     }
  2082.     adata[20] = data[81] & 07;    /* reverb rate */
  2083.     adata[21] = data[82];    /* Foot controller pitch */
  2084.     adata[22] = data[83];    /* Foot controller amp. */
  2085. }
  2086.  
  2087. #ifdef OLD
  2088. /*
  2089.  * Send a single parameter value.
  2090.  */
  2091. sendparam(param,val)
  2092. {
  2093.     sendmidi(0xf0);
  2094.     sendmidi(0x43);
  2095.     sendmidi(0x10);    /* Channel? */
  2096.     sendmidi(0x12);
  2097.     sendmidi(param);
  2098.     sendmidi(val);
  2099.     sendmidi(EOX);
  2100. }
  2101.  
  2102. /*
  2103.  * remotely press a key on the DX
  2104.  */
  2105. presskey(key,val)
  2106. {
  2107.     sendmidi(0xf0);
  2108.     sendmidi(0x43);
  2109.     sendmidi(0x10);    /* Channel? */
  2110.     sendmidi(0x08);
  2111.     sendmidi(key);
  2112.     sendmidi(val);
  2113.     sendmidi(EOX);
  2114. }
  2115.  
  2116. /*
  2117.  * tovmem
  2118.  *
  2119.  * convert a vced format voice to vmem format.
  2120.  */
  2121.  
  2122. tovmem(vdata,data)
  2123. char *vdata;    /* vced format data */
  2124. char *data;    /* vmem format */
  2125. {
  2126.     int vop, dop, n;
  2127.  
  2128.     for ( n=0; n<4; n++ ) {
  2129.         vop = Dopmap[n]*13;
  2130.         dop = Dopmap[n]*10;
  2131.         data[dop+0] = vdata[vop+0];    /* attack rate */
  2132.         data[dop+1] = vdata[vop+1];    /* decay 1 rate */
  2133.         data[dop+2] = vdata[vop+2];    /* decay 2 rate */
  2134.         data[dop+3] = vdata[vop+3];    /* release rate */
  2135.         data[dop+4] = vdata[vop+4];    /* decal 1 level */
  2136.         data[dop+5] = vdata[vop+5];    /* keyboard scaling level */
  2137.                 /* amp. mod. enab/eg bias sens/key velocity */
  2138.         data[dop+6]=(vdata[vop+8]<<6) | (vdata[vop+7]<<3) | vdata[vop+9];
  2139.         data[dop+7] = vdata[vop+10];    /* output level */
  2140.         data[dop+8] = vdata[vop+11];    /* osc. frequency */
  2141.                 /* key scaling rate/detune */
  2142.         data[dop+9] = (vdata[vop+6]<<3) | vdata[vop+12];
  2143.     }
  2144.         /* lfo sync/feedback level/algorithm */
  2145.     data[40] = (vdata[58]<<6) | (vdata[53]<<3) | vdata[52];
  2146.     data[41] = vdata[54];        /* lfo speed */
  2147.     data[42] = vdata[55];        /* lfo delay */
  2148.     data[43] = vdata[56];        /* pitch modulation depth */
  2149.     data[44] = vdata[57];        /* amplitude modulation depth */
  2150.         /* pitch mod. sens/amp. mod. sens/lfo wave */
  2151.     data[45] = (vdata[60]<<4) | (vdata[61]<<2) | vdata[59];
  2152.     data[46] = vdata[62];        /* transpose */
  2153.  
  2154.         /* chorus/playmode/sustain/portamento-foot/portamento-mode */
  2155.     data[48] = (vdata[70]<<4)|(vdata[63]<<3)|(vdata[68]<<2)|(vdata[69]<<1)
  2156.         | vdata[65];
  2157.  
  2158.     data[47] = vdata[64];        /* pitch bend range */
  2159.     data[49] = vdata[66];        /* portamento time */
  2160.     data[50] = vdata[67];        /* foot volume range */
  2161.     data[51] = vdata[71];        /* mod. wheel pitch mod. range */
  2162.     data[52] = vdata[72];        /* mod. wheel ampli. mod. range */
  2163.     data[53] = vdata[73];        /* breath pitch mod. range */
  2164.     data[54] = vdata[74];        /* breath ampli. mod. range */
  2165.     data[55] = vdata[75];        /* breath control pitch bias range */
  2166.     data[56] = vdata[76];        /* breath control EG bias range */
  2167.     for ( n=77; n<93; n++ )        /* voice name AND pitch EG rates */
  2168.         data[n-20] = vdata[n];
  2169. }
  2170. #endif
  2171.  
  2172. /* dx1nof - return a pointer to the voice name buried in data */
  2173. char *
  2174. dx1nof(data)
  2175. char *data;
  2176. {
  2177.     static char currbuff[DX100NSIZE+1];
  2178.     char *p;
  2179.     int m;
  2180.  
  2181.     p = currbuff;
  2182.     for ( m=0; m<10; m++ )
  2183.         *p++ = data[57+m];
  2184.     *p = '\0';
  2185.     return(currbuff);
  2186. }
  2187.  
  2188. /* dx1snof - set the voice name buried in data to name */
  2189. dx1snof(data,name)
  2190. char *data;
  2191. char *name;
  2192. {
  2193.     char *p;
  2194.     int m;
  2195.  
  2196.     for ( p=name,m=0; *p!='\0' && m<10; p++,m++ )
  2197.         data[57+m] = *p;
  2198.     for ( ; m<10; m++ )
  2199.         data[57+m] = ' ';
  2200. }
  2201.  
  2202. /* dx1sbulk - send a bulk dump to the DX-100 */
  2203. dx1sbulk(data)
  2204. char *data;
  2205. {
  2206.     int c, v, n, cksum;
  2207.  
  2208.     sendmidi(0xf0);
  2209.     sendmidi(0x43);
  2210.     sendmidi(Channel-1);    /* Channel # */
  2211.     sendmidi(0x04);
  2212.     sendmidi(0x20);
  2213.     sendmidi(0x00);
  2214.     cksum = 0;
  2215.     /* send 32 voices worth of data */
  2216.     for ( v=0; v<32; v++ ) {
  2217.         for ( n=0; n<DX100VSIZE; n++ ) {
  2218.             /* The DX100 can only handle 24 voices (but needs */
  2219.             /* to have 32 voices worth of data sent, anyway) */
  2220.             if ( v >= 24 && ( ! Tx81 ) )
  2221.                 c = 0;
  2222.             else
  2223.                 c = VOICEBYTE(data,v,n);
  2224.             sendmidi(c & 0xff);
  2225.             cksum += c;
  2226.         }
  2227.     }
  2228.     sendmidi((-cksum) & 0x7f);
  2229.     sendmidi(0xf7);
  2230. }
  2231.  
  2232. /* dx1gbulk - Request and read a bulk dump from the DX-100 */
  2233. dx1gbulk(data)
  2234. char *data;
  2235. {
  2236.     int c, n, v, b1, b2, cksum, ret = 1;
  2237.     long begin, toolong;
  2238.  
  2239.     setdxtx();
  2240.     flushmidi();
  2241.  
  2242.     sendmidi(0xf0);
  2243.     sendmidi(0x43);
  2244.     sendmidi(0x20 | (Channel-1) );    /* Channel # */
  2245.     sendmidi(4);            /* 4 == 32 voice bulk dump */
  2246.     sendmidi(EOX);            /* EOX */
  2247.  
  2248.     begin = milliclock();
  2249.     toolong = begin + 1000 * TIMEOUT;
  2250.  
  2251.     /* wait for the x43 byte starting the dump */
  2252.     while ( milliclock() < toolong ) {
  2253.         if ( STATMIDI && (c=(getmidi() & 0xff)) == 0x43 )
  2254.             break;
  2255.     }
  2256.     if ( c != 0x43 ) {
  2257.         Reason = "Timeout waiting for 0x43";
  2258.         goto getout;
  2259.     }
  2260.     getmidi();    /* channel # */
  2261.     getmidi();    /* format # */
  2262.     getmidi();    /* byte count high byte */
  2263.     getmidi();    /* byte count low byte */
  2264.  
  2265.     cksum = 0;
  2266.     /* 32 voices are dumped */
  2267.     for ( v=0; v<32; v++ ) {
  2268.         for ( n=0; n<DX100VSIZE; n++ ) {
  2269.             /* twiddle your thumbs, but not forever */
  2270.             while ( ! STATMIDI ) {
  2271.                 if ( milliclock() > toolong )
  2272.                     goto timeout;    /* the end of an era */
  2273.             }
  2274.             c = (getmidi() & 0xff);
  2275.             /* Ignore non-data bytes ? */
  2276.             if ( c & 0x80 )
  2277.                 continue;
  2278.             /* compute checksum */
  2279.             cksum += c;
  2280.             /* Only 24 voices are used on the DX100 */
  2281.             if ( v < 24 || Tx81 )
  2282.                 VOICEBYTE(data,v,n) = c;
  2283.         }
  2284.     }
  2285. timeout:
  2286.     if ( v < 32 ) {
  2287.         Reason = "Timeout while reading!";
  2288.         goto getout;
  2289.     }
  2290.     b1 = (getmidi() & 0xff);    /* Checksum */
  2291.     b2 = (getmidi() & 0xff);    /* EOX */
  2292.     cksum = (-cksum) & 0x7f;    /* convert to what we must match */
  2293.     if ( b2 != EOX )
  2294.         Reason = "EOX not received";
  2295.     else if ( b1 != cksum ) {
  2296.         static char ckbuff[80];
  2297.         sprintf(ckbuff,"Checksum doesn't match (got %d expected %d)",b1,cksum);
  2298.         /* Reason = "Checksum doesn't match"; */
  2299.         Reason = ckbuff;
  2300.     }
  2301.     else {
  2302.         Reason = "";
  2303.         ret = 0;    /* all's well */
  2304.     }
  2305. getout:
  2306.     return(ret);
  2307. }
  2308.  
  2309. #ifdef OLDSTUFF
  2310. dxchecksum(data)
  2311. char *data;
  2312. {
  2313.     int v, n, s=0;
  2314.  
  2315.     for ( v=0; v<DX100NVOICES; v++ ) {
  2316.         for ( n=0; n<DX100VSIZE; n++ ) {
  2317.             s += (int)(VOICEBYTE(data,v,n));
  2318.             while ( s > 128 )
  2319.                 s -= 128;
  2320.         }
  2321.     }
  2322.     return(128-s);
  2323. }
  2324. #endif
  2325.  
  2326. freqin(crs,fin)
  2327. {
  2328.     int n, f;
  2329.  
  2330.     txinit();
  2331.     f = txfreq[crs*16+fin];
  2332.     for ( n=0; n<txleng; n++ ) {
  2333.         if ( txfreq[txindex[n]] == f )
  2334.             return(n);
  2335.     }
  2336.     return(0);
  2337. }
  2338.  
  2339. freqout(v,acrs,afin)
  2340. int *acrs;
  2341. int *afin;
  2342. {
  2343.     int i;
  2344.  
  2345.     i = txindex[v];
  2346.     *acrs = i/16;
  2347.     *afin = i%16;
  2348. }
  2349.  
  2350. txinit()
  2351. {
  2352.     int n, k;
  2353.     char *parm;
  2354.  
  2355.     if ( txindex != NULL )
  2356.         return;
  2357.     /* create an array of indexes into txfreq, giving a sorted */
  2358.     /* list of unique frequencies. */
  2359.     txindex = (int *) alloc(sizeof(int) * 64 * 16);
  2360.     for ( n=0; n<64; n++ ) {
  2361.         for ( k=0; k<16; k++ ) {
  2362.             int freq = txfreq[n*16+k];
  2363.             register int i, f;
  2364.             register int *p, *endp;
  2365.  
  2366.             /* insertion sort, starting from top of already */
  2367.             /* sorted list, since the values we're inserting */
  2368.             /* are almost sorted already. */
  2369.             for ( i=txleng-1; i>=0; i-- ) {
  2370.                 if ( (f=txfreq[txindex[i]]) < freq )
  2371.                     break;
  2372.                 if ( f == freq )
  2373.                     goto dontadd;
  2374.             }
  2375.             i++;
  2376.             /* shift everything up one */
  2377.             p = &txindex[txleng];
  2378.             endp = &txindex[i];
  2379.             for ( ; p>endp; p-- )
  2380.                 *p = *(p-1);
  2381.             txindex[i] = 16*n+k;
  2382.             txleng++;
  2383.             dontadd: ;
  2384.         }
  2385.     }
  2386.     /* set the maximum value for the frequency parameters */
  2387.     parm = "op#freq";
  2388.     for ( n=1; n<=4; n++ ) {
  2389.         parm[2] = '0' + n;
  2390.         if ( (k=parmindex(parm)) >= 0 )
  2391.             P[k].p_max = txleng-1;
  2392.     }
  2393. }
  2394. SHAR_EOF
  2395. #    End of shell archive
  2396. exit 0
  2397. -- 
  2398. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2399. Have five nice days.
  2400.